package top.suyarong.ftbqsync.utils;


import org.bukkit.entity.Player;
import top.suyarong.ftbqsync.FTBQSync;

import java.lang.reflect.Method;

public class AstralSorceryUtil {

    private static final LogUtil log = LogUtil.getInstance();

    private static final FTBQSync plugin = FTBQSync.getInstance();

    private static final Class<?> PLAYER_PROGRESS;

    private static final Method PLAYER_PROGRESS_LOAD;

    private static final Method PLAYER_PROGRESS_STORE;

    private static final Class<?> RESEARCH_MANAGER;

    private static final Method RESEARCH_MANAGER_GET_PLAYER_PROGRESS;

    private static final Method RESEARCH_MANAGER_PUSH_PROGRESS_TO_CLIENT_UNSAFE;

    private static final Class<?> PERK_EFFECT_HELPER;
    // PERK_EFFECT_HELPER实例
    private static Object perkEffectHelperInstance = null;

    private static final Method HANDLE_PERK_MODIFICATION;


    public static final String UTIL_NAME = "AstralSorceryUtil ===> {0} 载入完成";

    static {

        PLAYER_PROGRESS = ReflectionUtil.getClass("hellfirepvp.astralsorcery.common.data.research.PlayerProgress");
        log.debug(plugin, UTIL_NAME, PLAYER_PROGRESS.getName());

        PLAYER_PROGRESS_LOAD = ReflectionUtil.getSingleParamMethod(PLAYER_PROGRESS, "load", NMSUtil.NBT_TAG_COMPOUND);
        log.debug(plugin, UTIL_NAME, PLAYER_PROGRESS_LOAD.getDeclaringClass().getName() + "." + PLAYER_PROGRESS_LOAD.getName() + "()");

        PLAYER_PROGRESS_STORE = ReflectionUtil.getSingleParamMethod(PLAYER_PROGRESS, "store", NMSUtil.NBT_TAG_COMPOUND);
        log.debug(plugin, UTIL_NAME, PLAYER_PROGRESS_STORE.getDeclaringClass().getName() + "." + PLAYER_PROGRESS_STORE.getName() + "()");

        RESEARCH_MANAGER = ReflectionUtil.getClass("hellfirepvp.astralsorcery.common.data.research.ResearchManager");
        log.debug(plugin, UTIL_NAME, RESEARCH_MANAGER.getName());

        RESEARCH_MANAGER_GET_PLAYER_PROGRESS = ReflectionUtil.getSingleParamMethod(RESEARCH_MANAGER, "getProgress", NMSUtil.CLAZZ_ENTITY_PLAYER);
        log.debug(plugin, UTIL_NAME, RESEARCH_MANAGER_GET_PLAYER_PROGRESS.getDeclaringClass().getName() + "." + RESEARCH_MANAGER_GET_PLAYER_PROGRESS.getName() + "()");

        RESEARCH_MANAGER_PUSH_PROGRESS_TO_CLIENT_UNSAFE =
                ReflectionUtil.getSingleParamMethod(RESEARCH_MANAGER, "pushProgressToClientUnsafe", NMSUtil.CLAZZ_ENTITY_PLAYER_MP);
        log.debug(plugin, UTIL_NAME, RESEARCH_MANAGER_PUSH_PROGRESS_TO_CLIENT_UNSAFE.getDeclaringClass().getName() + "." + RESEARCH_MANAGER_PUSH_PROGRESS_TO_CLIENT_UNSAFE.getName() + "()");

        PERK_EFFECT_HELPER = ReflectionUtil.getClass("hellfirepvp.astralsorcery.common.constellation.perk.PerkEffectHelper");
        log.debug(plugin, UTIL_NAME, PERK_EFFECT_HELPER.getName());

        HANDLE_PERK_MODIFICATION =
                ReflectionUtil.findMethod(PERK_EFFECT_HELPER, "handlePerkModification", void.class,
                        NMSUtil.CLAZZ_ENTITY_PLAYER, NMSUtil.MINECRAFT_SIDE, boolean.class);
        log.debug(plugin, UTIL_NAME, HANDLE_PERK_MODIFICATION.getDeclaringClass().getName() + "." + HANDLE_PERK_MODIFICATION.getName() + "()");

    }

    public static void setPlayerAstral(Player player, byte[] nbtData) {
        cleanData(player);
        restore(player, nbtData, true);
    }

    private static void restore(Player player, byte[] nbtData, boolean logFlag) {
        localLog("AstralSorceryUtil.restore ===> 开始同步玩家星辉数据", logFlag);
        Object playerProgress = getPlayerProgress(player);
        Object nbt = NMSUtil.bytes2Nbt(nbtData);
        localLog("即将同步的玩家数据 ===> {}", logFlag, nbt);
        Object nmsPlayer = NMSUtil.getNMSPlayer(player);

        Object perkEffectHelperInstance = getPerkEffectHelperInstance();
        localLog("perkEffectHelperInstance ===> {}", logFlag, perkEffectHelperInstance);

        ReflectionUtil.invokeMethod(HANDLE_PERK_MODIFICATION, perkEffectHelperInstance, nmsPlayer, NMSUtil.SERVER_SIDE, true);
        ReflectionUtil.invokeMethod(PLAYER_PROGRESS_LOAD, playerProgress, nbt);
        ReflectionUtil.invokeMethod(HANDLE_PERK_MODIFICATION, perkEffectHelperInstance, nmsPlayer, NMSUtil.SERVER_SIDE, false);
        localLog("PLAYER_PROGRESS_LOAD 完毕", logFlag);

        ReflectionUtil.invokeStaticMethod(RESEARCH_MANAGER_PUSH_PROGRESS_TO_CLIENT_UNSAFE, nmsPlayer);
        localLog("AstralSorceryUtil.restore ===> 同步完成", logFlag);

    }

    private static void cleanData(Player player) {
        restore(player, new byte[0], false);
    }

    private static void localLog(String msg, boolean flag, Object... args) {
        if (flag) log.debug(plugin, msg, args);
    }

    public static byte[] getData(Player player) {
        String playerName = player.getName();
        Object playerProgress = getPlayerProgress(player);
        Object nbt = NMSUtil.newNbtTagCompound();
        ReflectionUtil.invokeMethod(PLAYER_PROGRESS_STORE, playerProgress, nbt);
        log.debug(plugin, "AstralSorceryUtil.getData ===> 玩家 {} 当前星辉进度 &e{}", playerName, nbt);
        return NMSUtil.nbt2Bytes(nbt);
    }

    private static Object getPlayerProgress(Player player) {
        return ReflectionUtil.invokeStaticMethod(RESEARCH_MANAGER_GET_PLAYER_PROGRESS, NMSUtil.getNMSPlayer(player));
    }

    private static Object getPerkEffectHelperInstance() {
        if (perkEffectHelperInstance == null)
            perkEffectHelperInstance = ReflectionUtil.getStaticFieldValue(PERK_EFFECT_HELPER, "EVENT_INSTANCE");
        return perkEffectHelperInstance;
    }

    public static void init() {
        log.debug(plugin, "&eAstralSorceryUtil初始化完毕");
    }

}
